package gnss

import (
	"dgo/goutils/utils"
	"sync"
)

var (
	rtcm_raw_sat_obs_cnt int32 = 0
	rtcm_raw_sat_pool    sync.Pool
)

func init() {
	rtcm_raw_sat_pool.New = func() interface{} {
		return NewRtcmRawObsSat()
	}
}

func GetRtcmSigsFromMask(sigMask uint32) (rval []byte) {
	for i := U8_0; i < 32; i++ {
		if utils.GetBitValue0(uint64(sigMask), 31-i) == 1 {
			rval = append(rval, i+1)
		}
	}
	return rval
}

func GetRtcmSatFromMask(satmask uint64) (rval []byte) {
	for i := U8_0; i < 64; i++ {
		v := satmask >> (63 - i) & 1
		if v == 1 {
			rval = append(rval, i+1)
		}
	}
	return rval
}

func SigsToMask(mask *uint32, sigids ...byte) byte {
	for i := 0; i < len(sigids); i++ {
		*mask |= U32_1 << (31 - (sigids[i] - 1))
	}
	return utils.GetBitOnU32(*mask)
}

/*
*
 */
func CellMaskInfo(navisys byte, cellmask uint64, satmask uint64, sigmask uint32) string {
	siglst := GetRtcmSigsFromMask(sigmask)
	satlst := GetRtcmSatFromMask(satmask)
	//cellN := utils.GetBitOnU64(cellmask)
	sigN := byte(len(siglst))
	satN := byte(len(satlst))

	var bb utils.BytesBuilder
	bb.AppendStr("sat:")
	for i := U8_0; i < satN; i++ {
		bb.Appendf("%.2d ", satlst[i])
	}
	bb.AppendStr("\r\n")

	bb.AppendStr("sig:")
	for i := U8_0; i < sigN; i++ {
		bb.Appendf("%s ", SigiRinexCode(navisys, siglst[i]))
	}
	bb.AppendStr("\r\n")

	{
		bb.AppendStr("cell:\n")

		bb.AppendStr("   ")
		for i := U8_0; i < sigN; i++ {
			bb.Appendf("%s\t", SigiRinexCode(navisys, siglst[i]))
		}
		bb.AppendStr("\r\n")
		n := int(satN * sigN)
		u64 := cellmask
		j := 0
		for i := 0; i < n; i++ {
			if byte(i)%sigN == 0 {
				bb.Appendf("%.2d ", satlst[j])
				j++
			}
			v := (u64 >> (n - 1 - i)) & 1
			bb.Appendf("%d\t", v)
			if i > 0 && (byte(i+1)%sigN == 0) {
				bb.AppendStr("\r\n")
			}
		}
	}
	return bb.String()
}

/*
*

	sigid > 0
*/
func SetSigMaskOn(mask *uint32, sigid byte) bool {
	premask := *mask
	*mask |= U32_1 << (31 - (sigid - 1))
	return premask != *mask
}

func PrintRtcmInfoFromMask(naviSys byte, sigMask uint32) string {
	var bb utils.BytesBuilder
	for i := U8_0; i < 32; i++ {
		if utils.GetBitValue0(uint64(sigMask), 31-i) == 1 {
			if bb.Len() > 0 {
				bb.AppendStr(" ")
			}
			bb.Appendf("%s(%.2d)", GetSignCode(i+1, naviSys), i+1)
		}
	}
	return bb.String()
}

func WriteMsm2YObsEx(yobsEpoch *GnssYObsEpoch, msm RtcmRawMsm, checkfn func(navisys, satid, ysigid byte) bool) {
	msm.RangeObs(func(sigobs *RtcmRawSatSigObs) {
		satid := sigobs.SatId
		naviSys := sigobs.NaviSys
		if satid > 100 {
			if naviSys == SYS_GPS {
				naviSys = SYS_SBS
				satid -= 100
			} else if naviSys == SYS_QZS {
				satid -= 192
			}
		}

		sigid := sigobs.SigId
		if sigid > 0 && satid > 0 {
			sigid = sigid - 1
			if checkfn == nil || checkfn(naviSys, satid, sigid) {
				obs := yobsEpoch.CheckGetRawObs(naviSys, satid)
				obs.PsRngV[sigid] = sigobs.GetPsRng()
				obs.PhRngV[sigid] = sigobs.GetPhRng()
				obs.Doppler[sigid] = sigobs.GetDoppler()
				obs.Cnr[sigid] = sigobs.Cnr
				obs.LkT[sigid] = sigobs.GetLockTime()
			}
		}
	})
}

// 打包成msm4的数据包
// 可能出现Panic, 外层需要做处理
// 使用checksigfn判断信号是否需要添加
func EncodeMsm4FromObsV2(obs *RtcmRawMsmObs, checksigfn func(satid uint16, sigid byte) bool, getMsmFun func() *RtcmRawMsm4, onDoneMsmFun func(msm *RtcmRawMsm4)) (n int) {
	n = 0
	var satPrn byte = 1
	var endPrn byte = 0
	var maxEndPrn byte = 0
	var newmask uint32
	var sigN byte
	var satlst []byte
	var maxSatN byte = 0
	for {
		msm4 := getMsmFun()

		maxEndPrn = 0
		maxSatN = 0

		newmask, sigN, endPrn, satlst = obs.ExtractMsmPackEx(satPrn, maxEndPrn, maxSatN, checksigfn)

		if len(satlst) == 0 { // 没有符合条件的卫星数据, 可能是
			return
		}

		msm4.Header.SetSats(satlst)
		msm4.Header.SignalMask = newmask
		msm4.Header.SigN = sigN
		msm4.Header.CellN, msm4.Header.CellMask = obs.ExtractCellMask(msm4.Header.SatMask, msm4.Header.SignalMask)

		msm4.CopyFromObs(obs)
		onDoneMsmFun(msm4)
		n++
		endPrn++
		satPrn = endPrn
	}
	return
}

/*
打包成msm4的数据包
可能出现Panic, 外层需要做处理
*/
func EncodeMsm4FromObsV1(obs *RtcmRawMsmObs, holdSigs, fixedSigs []byte, getMsmFun func() *RtcmRawMsm4, onDoneMsmFun func(msm *RtcmRawMsm4)) (n int) {
	n = 0
	var satPrn byte = 1
	var endPrn byte = 0
	var maxEndPrn byte = 0
	var newmask uint32
	var sigN byte
	var satlst []byte
	var maxSatN byte = 0
	for {
		msm4 := getMsmFun()

		maxEndPrn = 0
		maxSatN = 0
		if msm4.Header.EncodeType == 0 { // 分割BD3
			if msm4.Header.NaviSys == SYS_BD && satPrn == 1 { // 切割BD2/BD3(华测进行了切割, 千寻没有切割, 切割后对老设备兼容较好)
				maxEndPrn = 16
			}
		} else if msm4.Header.EncodeType == 2 { // 最多12颗卫星
			if msm4.Header.NaviSys == SYS_BD && satPrn == 1 { // 切割BD2/BD3(华测进行了切割, 千寻没有切割, 切割后对老设备兼容较好)
				maxSatN = 12
			}
		}
		newmask, sigN, endPrn, satlst = obs.ExtractMsmPack(satPrn, maxEndPrn, maxSatN, holdSigs, fixedSigs[:]...)
		if len(satlst) == 0 && maxEndPrn == 16 { // 没有16以下卫星
			newmask, sigN, endPrn, satlst = obs.ExtractMsmPack(satPrn, 0, maxSatN, holdSigs, fixedSigs[:]...)
		}

		if len(satlst) == 0 { // 没有符合条件的卫星数据, 可能是
			return
		}

		msm4.Header.SetSats(satlst)
		msm4.Header.SignalMask = newmask
		msm4.Header.SigN = sigN
		msm4.Header.CellN, msm4.Header.CellMask = obs.ExtractCellMask(msm4.Header.SatMask, msm4.Header.SignalMask)

		msm4.CopyFromObs(obs)
		onDoneMsmFun(msm4)
		n++
		endPrn++
		satPrn = endPrn
	}
	return
}

/*
**

	打包成msm7的数据包
	  可能出现Panic, 外层需要做处理
*/
func EncodeMsm7FromObs(obs *RtcmRawMsmObs, holdSigs, fixedSigs []byte, getMsmFun func() *RtcmRawMsm7, onDoneMsmFun func(msm *RtcmRawMsm7)) (n int) {
	n = 0
	var satPrn byte = 1
	var endPrn byte = 0
	var maxEndPrn byte = 0
	var newmask uint32
	var sigN byte
	var satlst []byte
	for {
		msm7 := getMsmFun()

		maxEndPrn = 0
		if msm7.Header.EncodeType == 0 {
			if msm7.Header.NaviSys == SYS_BD && satPrn == 1 { // 切割BD2/BD3(华测进行了切割, 千寻没有切割, 切割后对老设备兼容较好)
				maxEndPrn = 16
			}
		}
		newmask, sigN, endPrn, satlst = obs.ExtractMsmPack(satPrn, maxEndPrn, 0, holdSigs, fixedSigs[:]...)
		if len(satlst) == 0 && maxEndPrn == 16 { // 没有16以下卫星
			newmask, sigN, endPrn, satlst = obs.ExtractMsmPack(satPrn, 0, 0, holdSigs, fixedSigs[:]...)
		}

		if len(satlst) == 0 { // 没有符合条件的卫星数据, 可能是
			return
		}

		msm7.Header.SetSats(satlst)
		msm7.Header.SignalMask = newmask
		msm7.Header.SigN = sigN
		msm7.Header.CellN, msm7.Header.CellMask = obs.ExtractCellMask(msm7.Header.SatMask, msm7.Header.SignalMask)

		msm7.CopyFromObs(obs)
		onDoneMsmFun(msm7)
		n++
		endPrn++
		satPrn = endPrn
	}
	return
}

/*
**

	打包成msm4的数据包
	  可能出现Panic, 外层需要做处理
*/
func EncodeMsm4FromObs(obs *RtcmRawMsmObs, holdSigs, fixedSigs []byte, getMsmFun func() *RtcmRawMsm4, encodeMsmFun func(msm *RtcmRawMsm4)) (n int) {
	n = 0
	var satPrn byte = 1
	var endPrn byte = 0
	var maxEndPrn byte = 0
	var newmask uint32
	var sigN byte
	var satlst []byte
	for {
		msm4 := getMsmFun()

		maxEndPrn = 0
		if msm4.Header.EncodeType == 0 {
			if msm4.Header.NaviSys == SYS_BD && satPrn == 1 { // 切割BD2/BD3(华测进行了切割, 千寻没有切割, 切割后对老设备兼容较好)
				maxEndPrn = 16
			}
		}

		newmask, sigN, endPrn, satlst = obs.ExtractMsmPack(satPrn, maxEndPrn, 0, holdSigs, fixedSigs[:]...)
		if len(satlst) == 0 && maxEndPrn == 16 { // 没有16以下卫星
			newmask, sigN, endPrn, satlst = obs.ExtractMsmPack(satPrn, 0, 0, holdSigs, fixedSigs[:]...)
		}

		if len(satlst) == 0 { // 没有符合条件的卫星数据, 可能是
			return
		}
		//siglst := PrintRtcmInfoFromMask(msm4.Header.NaviSys, newmask)
		//fmt.Println(siglst)

		msm4.Header.SetSats(satlst)
		msm4.Header.SignalMask = newmask
		msm4.Header.SigN = sigN
		msm4.Header.CellN, msm4.Header.CellMask = obs.ExtractCellMask(msm4.Header.SatMask, msm4.Header.SignalMask)

		//str := CellMaskInfo(msm4.Header.NaviSys, msm4.Header.CellMask, msm4.Header.SatMask, msm4.Header.SignalMask)
		//fmt.Println(str)

		existobs := obs.ExistsObs(endPrn + 1)
		if msm4.Header.EpochEndFlag {
			if existobs {
				msm4.Header.EpochEndFlag = false
			}
		}

		msm4.CopyFromObs(obs)
		encodeMsmFun(msm4)
		n++
		endPrn++
		satPrn = endPrn
		if !existobs {
			return
		}

		//return
		//
		//msm4.MakeMsmHeaderStep0(obs)
		//
		//if len(holdSigs) > 0 {
		//	msm4.Header.DelSigsFromMaskEx(holdSigs[:]...)
		//}
		//
		//if satPrn > 1 {
		//	msm4.Header.DelSatsFromMaskEx(0, satPrn-1)
		//}
		//
		//msm4.Header.SetSigMask(obs.MakeSigMask(msm4.Header.SatMask, msm4.Header.SignalMask))
		//
		//if len(fixedSigs) > 0 {
		//	msm4.Header.SetSigsToMask(fixedSigs[:]...)
		//}
		//
		//if msm4.Header.SatN*msm4.Header.SigN <= 64 {
		//	msm4.MakeMsmHeaderStep1(obs)
		//	msm4.CopyFromObs(obs)
		//	encodeMsmFun(msm4)
		//	n++
		//	return
		//} else {
		//
		//	if msm4.Header.EncodeType == 0 {
		//		if msm4.Header.NaviSys == SYS_BD { // 切割BD2/BD3(华测进行了切割, 千寻没有切割, 切割后对老设备兼容较好)
		//			if satPrn < 16 {
		//				endPrn = 16
		//			}
		//		}
		//	} else {
		//
		//		n1 := 64 / msm4.Header.SigN // 可以处理存放多少颗卫星
		//
		//		endPrn = msm4.Header.StatSatOn(satPrn, 0, n1)
		//		if satPrn == 0 {
		//			break
		//		}
		//		//
		//		//// 切割BD2/BD3(华测进行了切割, 千寻没有切割, 切割后对老设备兼容较好)
		//		//if msm4.Header.NaviSys == SYS_BD && satPrn < 16 && endPrn > 16 {
		//		//	endPrn = 16
		//		//}
		//	}
		//
		//	endPrn++
		//	satPrn = endPrn
		//
		//	if msm4.Header.EpochEndFlag {
		//		if msm4.Header.StatSatOn(satPrn, 0, 1) > 0 { // 还有 存在数据的卫星
		//			msm4.Header.EpochEndFlag = false
		//		}
		//	}
		//
		//	msm4.Header.DelSatsFromMaskEx(satPrn, 0)
		//	msm4.Header.SetSigMask(obs.MakeSigMask(msm4.Header.SatMask, msm4.Header.SignalMask))
		//	msm4.MakeMsmHeaderStep1(obs)
		//	msm4.CopyFromObs(obs)
		//	encodeMsmFun(msm4)
		//	n++
		//
		//}
	}
	return
}

/*
*

	使用指针要不是传值
*/
func ResetSigListFloat64(lst *[MAX_SIGN_LEN]float64) {
	for i := 0; i < len(lst); i++ {
		lst[i] = 0
	}
}

func ResetSigListFloat32(lst *[MAX_SIGN_LEN]float32) {
	for i := 0; i < len(lst); i++ {
		lst[i] = 0
	}
}

func ResetSigListUint16(lst *[MAX_SIGN_LEN]uint16) {
	for i := 0; i < len(lst); i++ {
		lst[i] = 0
	}
}

func ResetSigListInt16(lst *[MAX_SIGN_LEN]int16) {
	for i := 0; i < len(lst); i++ {
		lst[i] = 0
	}
}

func ResetSigListByte(lst *[MAX_SIGN_LEN]byte) {
	for i := 0; i < len(lst); i++ {
		lst[i] = 0
	}
}
